package com.aloda.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.excel.EasyExcel;
import com.aloda.cache.RedisUtils;
import com.aloda.constant.ExceptionConstant;
import com.aloda.context.AdminBaseContext;
import com.aloda.dto.appCategory.AppCategoryAddDTO;
import com.aloda.dto.appCategory.AppCategoryEditDTO;
import com.aloda.entity.*;
import com.aloda.enums.AppCategoryStatusEnum;
import com.aloda.exception.BaseException;
import com.aloda.mapper.*;
import com.aloda.query.AppCategoryPageDTO;
import com.aloda.result.PageResult;
import com.aloda.service.AppCategoryService;
import com.aloda.utils.CheckUtils;
import com.aloda.vo.appCategory.AppCategoryExportVO;
import com.aloda.vo.appCategory.AppCategoryListVO;
import com.aloda.vo.appCategory.AppCategoryPageVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author aloda
* @description 针对表【app_category(应用分类表)】的数据库操作Service实现
* @createDate 2025-03-15 08:19:10
*/
@Service
public class AppCategoryServiceImpl extends ServiceImpl<AppCategoryMapper, AppCategory> implements AppCategoryService {

    @Resource
    private AppCategoryMapper appCategoryMapper;

    @Resource
    private AppMapper appMapper;

    @Resource
    private QuestionMapper questionMapper;

    @Resource
    private ScoringResultMapper scoringResultMapper;

    @Resource
    private EmpMapper empMapper;

    @Resource
    private RedisUtils redisUtils;

    @Override
    public long addAppCategory(AppCategoryAddDTO appCategoryAddDTO) {
        // 1. 数据格式校验
        if (!CheckUtils.checkCategoryName(appCategoryAddDTO.getCategoryName())) {
            throw new BaseException(ExceptionConstant.FORMAT_ERROR);
        }
        // 2. 写入默认字段
        AppCategory appCategory = new AppCategory();
        Long currentId = AdminBaseContext.getCurrentId();
        Emp emp = empMapper.selectById(currentId);
        BeanUtil.copyProperties(appCategoryAddDTO, appCategory);
        appCategory.setUserId(currentId);
        appCategory.setCreateUser(emp.getEmpAccount());
        appCategory.setCreateTime(LocalDateTime.now());
        appCategory.setUpdateTime(LocalDateTime.now());
        // 3. 存储数据
        appCategoryMapper.insert(appCategory);
        // 删除缓存
        redisUtils.deleteNormalCategoryList();
        // 4. 返回 id
        return appCategory.getId();
    }

    @Override
    public PageResult<AppCategoryPageVO> pageQuery(AppCategoryPageDTO appCategoryPageDTO) {
        Page<AppCategory> page = appCategoryPageDTO.toMpPageDefaultSortByUpdateTimeDesc();
        LambdaQueryWrapper<AppCategory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(appCategoryPageDTO.getCategoryName() != null, AppCategory::getCategoryName, appCategoryPageDTO.getCategoryName())
                .eq(appCategoryPageDTO.getCategoryStatus() != null, AppCategory::getCategoryStatus, appCategoryPageDTO.getCategoryStatus())
                .like(appCategoryPageDTO.getCreateUser() != null, AppCategory::getCreateUser, appCategoryPageDTO.getCreateUser())
                .between(appCategoryPageDTO.getBeginTime() != null && appCategoryPageDTO.getEndTime() != null,
                        AppCategory::getCreateTime, appCategoryPageDTO.getBeginTime(), appCategoryPageDTO.getEndTime());
        appCategoryMapper.selectPage(page, queryWrapper);
        return PageResult.of(page, AppCategoryPageVO.class);
    }

    /**
     * 编辑应用分类
     * @param appCategoryEditDTO 编辑应用分类的 DTO
     * @return
     */
    @Override
    public long editAppCategory(AppCategoryEditDTO appCategoryEditDTO) {
        if (!CheckUtils.checkCategoryName(appCategoryEditDTO.getCategoryName())) {
            throw new BaseException(ExceptionConstant.FORMAT_ERROR);
        }
        AppCategory appCategory = new AppCategory();
        BeanUtil.copyProperties(appCategoryEditDTO, appCategory);
        appCategory.setUpdateTime(LocalDateTime.now());
        this.updateById(appCategory);
        // 删除缓存
        redisUtils.deleteNormalCategoryList();
        return appCategory.getId();
    }

    /**
     * 导出应用分类表格
     *
     * @param response HttpServletResponse 对象
     * @param ids      要导出的应用分类 ID 列表
     */
    public void exportAppCategoryToExcel(HttpServletResponse response, List<Long> ids) {
        try {
            // 设置响应头
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("应用分类信息表", "UTF-8").replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");

            // 查询所有信息，如果 ids 为空查询所有信息，否则查询对应信息
            LambdaQueryWrapper<AppCategory> queryWrapper = new LambdaQueryWrapper<>();
            List<AppCategory> appCategoryList;
            if (ids.isEmpty()) {
                appCategoryList = appCategoryMapper.selectList(queryWrapper);
            } else {
                appCategoryList = appCategoryMapper.selectBatchIds(ids);
            }

            // 转换为导出 VO
            List<AppCategoryExportVO> exportVOList = appCategoryList.stream()
                    .map(appCategory -> {
                        AppCategoryExportVO exportVO = new AppCategoryExportVO();
                        BeanUtil.copyProperties(appCategory, exportVO);
                        exportVO.setCategoryStatus(appCategory.getCategoryStatus().getDesc());
                        return exportVO;
                    })
                    .collect(Collectors.toList());

            // 使用 EasyExcel 导出
            EasyExcel.write(response.getOutputStream(), AppCategoryExportVO.class)
                    .sheet("应用分类信息")
                    .doWrite(exportVOList);
        } catch (IOException e) {
            throw new RuntimeException(ExceptionConstant.EXPORT_EXCEL_ERROR, e);
        }
    }

    /**
     * 删除应用分类
     *
     * @param ids
     * @return
     */
    @Transactional
    @Override
    public boolean deleteAppCategory(List<Long> ids) {
        // 1.找出所有分类下的应用
        LambdaQueryWrapper<App> appLambdaQueryWrapper = new LambdaQueryWrapper<>();
        appLambdaQueryWrapper.in(App::getCategoryId, ids);
        List<App> appList = appMapper.selectList(appLambdaQueryWrapper);
        if (!appList.isEmpty()) {
            throw new BaseException(ExceptionConstant.APP_CATEGORY_HAS_APP);
        }
        // 2.删除id对应的应用分类
        appCategoryMapper.deleteByIds(ids);
        // 3.删除缓存
        redisUtils.deleteNormalCategoryList();
        return true;
    }

    /**
     * 获取所有正常的应用分类
     *
     * @return
     */
    @Override
    public List<AppCategoryListVO> getNormalCategoryList() {
        // 1.查询缓存
        List<AppCategoryListVO> normalCategoryListFromCache = redisUtils.getNormalCategoryListFromCache();
        if (CollectionUtil.isNotEmpty(normalCategoryListFromCache)) {
            return normalCategoryListFromCache;
        }
        // 2.缓存没有则查询数据库
        LambdaQueryWrapper<AppCategory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AppCategory::getCategoryStatus, AppCategoryStatusEnum.NORMAL);
        List<AppCategory> list = this.list(queryWrapper);
        List<AppCategoryListVO> appCategoryListVOS = list.stream().map(appCategory -> BeanUtil.copyProperties(appCategory, AppCategoryListVO.class)).toList();
        // 3.放入缓存
        redisUtils.saveNormalCategoryListToCache(appCategoryListVOS);
        return appCategoryListVOS;
    }
}




